﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.ComponentModel;
using DevExpress.XtraBars;
using DevExpress.XtraTab;

namespace Marmat.Template.WinForm
{

    /// <summary>
    /// 页签容器控件
    /// </summary>
    public partial class TabFormPanelControl : UserControl
    {

        private XtraTabPage selectPage;
        private XtraTabPage hotTrackedPage;
        private readonly List<Form> forms = new List<Form>();

        /// <summary>
        /// 构建tab的实例。
        /// </summary>
        public TabFormPanelControl()
        {
            InitializeComponent();
            this.xtraTabControl1.SelectedPageChanging += XtraTabControl1_SelectedPageChanging;
        }

        private void XtraTabControl1_SelectedPageChanging(object sender, TabPageChangingEventArgs e)
        {
            this.selectPage = this.xtraTabControl1.SelectedTabPage;
        }

        /// <summary>
        /// 获取或设置选定的窗体对象。
        /// </summary>
        [DefaultValue(null)]
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public System.Windows.Forms.Form SelectedForm
        {
            get
            {
                if (this.xtraTabControl1?.SelectedTabPage is not null)
                    return this.xtraTabControl1.SelectedTabPage.Tag as System.Windows.Forms.Form;
                else
                    return null;
            }
            set
            {
                if (value is null)
                    throw new ArgumentNullException($"{nameof(SelectedForm)} 属性不能设为 Null 值。");
                var page = this.xtraTabControl1.TabPages.FirstOrDefault(x => x.Tag.Equals(value));
                if (page is null)
                    throw new NullReferenceException("已打开窗体集合中不存在此窗体。");
                else
                    this.xtraTabControl1.SelectedTabPage = page;

            }
        }

        /// <summary>
        /// 获取或设置选定的窗体名称
        /// </summary>
        [Browsable(false)]
        [DefaultValue(null)]
        public string SelectedFormName
        {
            get => this.SelectedForm?.Name;
            set => this.SelectedForm = this.Forms.FirstOrDefault(x => x.Name == value);
        }

        /// <summary>
        /// 获取或设置是否显示选项卡的头部区域。
        /// </summary>
        [DefaultValue(true)]
        public bool ShowTabHeader
        {
            get => this.xtraTabControl1.ShowTabHeader == DevExpress.Utils.DefaultBoolean.Default;
            set => this.xtraTabControl1.ShowTabHeader = value ? DevExpress.Utils.DefaultBoolean.Default : DevExpress.Utils.DefaultBoolean.False;
        }

        /// <summary>
        /// 获取已打开的窗体集合。
        /// </summary>
        public Form[] Forms => this.forms.ToArray();

        private void xtraTabControl1_CloseButtonClick(object sender, EventArgs e)
        {
            DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs args = (DevExpress.XtraTab.ViewInfo.ClosePageButtonEventArgs)e;
            XtraTabPage page = (XtraTabPage)args.Page;
            if (page != null && page.Tag is System.Windows.Forms.Form frm)
            {
                frm.Close();
            }
        }

        private void XtraTabForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.forms.Remove(sender as Form);
            foreach (XtraTabPage item in this.xtraTabControl1.TabPages)
            {
                if (item.Tag == sender)
                {
                    this.xtraTabControl1.TabPages.Remove(item);
                    item.Dispose();

                    if (this.selectPage?.IsDisposed == false)
                        this.xtraTabControl1.SelectedTabPage = this.selectPage;
                    return;
                }
            }
        }

        private void XtraTabControl1_HotTrackedPageChanged(object sender, TabPageChangedEventArgs e)
        {
            hotTrackedPage = e.Page;
        }

        private void XtraTabControl1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && this.hotTrackedPage != null)
            {
                this.popupMenu1.ShowPopup(MousePosition);
            }
        }

        /// <summary>
        /// 关闭当前页签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseCurrentPage_ItemClick(object sender, ItemClickEventArgs e)
        {
            if (this.xtraTabControl1.SelectedTabPage?.Tag is System.Windows.Forms.Form form)
            {
                form.Close();
            }
        }

        /// <summary>
        /// 关闭其他页签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseOtherPage_ItemClick(object sender, ItemClickEventArgs e)
        {
            List<System.Windows.Forms.Form> forms = new List<System.Windows.Forms.Form>();
            foreach (XtraTabPage page in this.xtraTabControl1.TabPages)
            {
                if (page != this.xtraTabControl1.SelectedTabPage && page.Tag is System.Windows.Forms.Form form)
                    forms.Add(form);
            }

            foreach (var form in forms)
            {
                form.Close();
            }
        }

        /// <summary>
        /// 关闭左侧页签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseLeftPage_ItemClick(object sender, ItemClickEventArgs e)
        {
            List<System.Windows.Forms.Form> forms = new List<System.Windows.Forms.Form>();
            foreach (XtraTabPage page in this.xtraTabControl1.TabPages)
            {
                if (page == this.xtraTabControl1.SelectedTabPage)
                    break;
                if (page.Tag is System.Windows.Forms.Form form)
                    forms.Add(form);
            }

            foreach (var form in forms)
            {
                form.Close();
            }
        }

        /// <summary>
        /// 关闭右侧页签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseRightPage_ItemClick(object sender, ItemClickEventArgs e)
        {
            bool start = false;
            List<System.Windows.Forms.Form> forms = new List<System.Windows.Forms.Form>();
            foreach (XtraTabPage page in this.xtraTabControl1.TabPages)
            {
                if (start && page.Tag is System.Windows.Forms.Form form)
                    forms.Add(form);

                if (page == this.xtraTabControl1.SelectedTabPage)
                    start = true;
            }

            foreach (var form in forms)
            {
                form.Close();
            }
        }

        /// <summary>
        /// 关闭全部页签
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CloseAllPage_ItemClick(object sender, ItemClickEventArgs e)
        {
            List<System.Windows.Forms.Form> forms = new List<System.Windows.Forms.Form>();
            foreach (XtraTabPage page in this.xtraTabControl1.TabPages)
            {
                if (page.Tag is System.Windows.Forms.Form form)
                    forms.Add(form);
            }

            foreach (var form in forms)
            {
                form.Close();
            }
        }

        /// <summary>
        /// 显示菜单时执行,用于控制菜单的项是否显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PopupMenu1_Popup(object sender, EventArgs e)
        {
            this.closeOtherPage.Enabled = this.xtraTabControl1.TabPages.Count > 1 ? true : false;
            bool start = true;
            int index = this.xtraTabControl1.TabPages.Count(page =>
            {
                if (page == this.hotTrackedPage)
                    start = false;
                return start;
            });
            this.closeLeftPage.Enabled = index > 0 ? true : false;
            this.closeRightPage.Enabled = index < this.xtraTabControl1.TabPages.Count - 1 ? true : false;
        }

        /// <summary>
        /// 添加子窗体
        /// </summary>
        /// <param name="form"></param>
        public void AddForm(System.Windows.Forms.Form form)
        {
            if (form is null) { throw new ArgumentNullException(nameof(form)); }
            XtraTabControl tab = this.xtraTabControl1;
            DevExpress.XtraTab.XtraTabPage page = new DevExpress.XtraTab.XtraTabPage();
            page.Name = form.Name;
            page.Text = form.Text;
            page.Tag = form;
            form.TopLevel = false;
            form.Parent = page;
            form.Dock = System.Windows.Forms.DockStyle.Fill;
            form.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            form.FormClosed += this.XtraTabForm_FormClosed;
            form.TextChanged += this.XtraTabForm_TextChanged;
            page.Controls.Add(form);
            if (form.ShowIcon)
                page.ImageOptions.Image = form.Icon.ToBitmap().GetThumbnailImage(16, 16, delegate { return true; }, IntPtr.Zero);
            Marmat.Forms.WindowsAPI.LockWindowUpdate(this.Handle.ToInt32());
            form.Show();
            if (form.IsDisposed == false)
            {
                this.forms.Add(form);
                tab.TabPages.Add(page);
                tab.SelectedTabPage = page;
            }
            else
                page.Dispose();
            Marmat.Forms.WindowsAPI.LockWindowUpdate(IntPtr.Zero.ToInt32());
        }

        private void XtraTabForm_TextChanged(object sender, EventArgs e)
        {
            if (sender is System.Windows.Forms.Control panel)
            {
                var page = this.xtraTabControl1.TabPages.FirstOrDefault(x => x.Tag == panel);
                if (page != null)
                    page.Text = panel.Text;
            }
        }

        /// <summary>
        /// 是否包含指定名称的窗体
        /// </summary>
        /// <param name="name">窗体名称</param>
        /// <returns></returns>
        public bool ContainsForm(string name)
        {
            return this.forms.Exists(x => x.Name == name);
        }
    }
}